CloakBrowser 源码级反指纹 Chromium 与 BrowserStation 集成实战
CloakBrowser:源码级反指纹 Chromium 与 BrowserStation 集成实战
市面上大多数「反检测浏览器」的技术路线是注入 JS 或改启动参数,每次 Chrome 升级就断一次,而且注入痕迹本身就是检测信号。CloakBrowser 走的是另一条路——直接改 Chromium C++ 源码,重新编译生成二进制。这篇文章介绍它的原理、用法、与同类方案的差异,以及如何替换 BrowserStation 里的 Chrome 容器,把无头浏览器池升级为反检测池。
一、CloakBrowser 是什么
CloakBrowser 是一个开源的隐身 Chromium 发行版,包含两个东西:
- 一个重新编译的 Chromium 二进制(约 200MB),在源码层面打了 57+ 处指纹补丁
- Python/JS 包装器,作为 Playwright/Puppeteer 的 drop-in 替代
核心主张是「同一套 Playwright API,换三行导入就能绕过大多数反机器人系统」:
# 从这个
from playwright.sync_api import sync_playwright
pw = sync_playwright().start()
browser = pw.chromium.launch()
# 改成这个
from cloakbrowser import launch
browser = launch()
剩下的代码一行不用改。
已通过的检测
官方列出的测试结果(2026 年 4 月):
| 检测服务 | 原生 Playwright | CloakBrowser |
|---|---|---|
| reCAPTCHA v3 分数 | 0.1(机器人) | 0.9(人类) |
| Cloudflare Turnstile | Fail | Pass |
| FingerprintJS | 被检测 | Pass |
| BrowserScan | 被检测 | Normal 4/4 |
navigator.webdriver |
true |
false |
| TLS 指纹 | 与 Chrome 不符 | 完全一致 |
| UA | HeadlessChrome |
Chrome/146.0.0.0 |
已知局限:DataDome、Kasada、Akamai 这些激进站点仍需要配合住宅代理 + 有头模式 + 字体包才能稳定过。
二、为什么源码级补丁是关键
要理解 CloakBrowser 的价值,先看看同赛道其他方案怎么做。
路线 1:JS 注入(playwright-stealth、puppeteer-extra-stealth)
通过 page.addInitScript() 在页面加载前注入脚本,覆盖 navigator.webdriver、window.chrome、canvas 等属性。
问题:
- 注入本身可见。检测脚本可以跑
navigator.webdriver.toString(),看返回值是不是被篡改过的 getter - Chrome 每次更新都可能改这些接口实现,注入脚本立刻失效
- TLS 指纹改不了(在网络栈里,JS 碰不到)
路线 2:启动参数(undetected-chromedriver)
通过删除 --enable-automation 等启动参数、改启动命令规避检测。
问题:
- 只能改浏览器对外暴露的命令行层面
- canvas 噪声、WebGL 渲染结果、音频 AudioContext 等底层指纹完全没动
- 高级检测(比如 Incolumitas)秒穿
路线 3:Firefox 补丁(Camoufox)
改 Firefox 源码,类似思路但换了引擎。
问题:
- Playwright 对 Firefox 支持弱于 Chromium
- 真实 Chrome 用户占比压倒性,Firefox 指纹反而更显眼
- 2026 年初一度停更,目前还在不稳定 beta
路线 4:源码级 C++ 补丁(CloakBrowser)
直接改 Chromium 的 C++ 源码,然后编译成二进制:
- Canvas 噪声在
CanvasRenderingContext2D的getImageData里加 - WebGL 指纹在
GLContext::GetParameter里改 - AudioContext 在
OfflineAudioContext采样处加扰动 - TLS 指纹在网络栈的 BoringSSL 层调整 cipher 顺序
navigator.webdriver直接在 Blink 里写死false
优势:
- 站点拿到的是「一个真实 Chrome 的真实行为」,没有 JS 注入痕迹
- Chrome 升级时只需 rebase 补丁(类似 Ungoogled Chromium 的做法),不需要重新搞对抗逻辑
- TLS/ja3/ja4 与真实 Chrome 完全一致
代价:
- 需要自己维护编译基础设施(CloakBrowser 提供 CI 产物)
- 二进制体积大(~200MB 下载)
- 补丁跟不上 Chrome 主版本就会落后
三、快速上手
安装
Python:
pip install cloakbrowser
# 如果要用代理 IP 自动推断时区和地理位置
pip install cloakbrowser[geoip]
Node.js:
npm install cloakbrowser playwright-core
# 或者用 Puppeteer
npm install cloakbrowser puppeteer-core
首次运行会从 cloakbrowser.dev 自动下载对应平台的 Chromium 二进制(Linux x64/arm64、macOS x86/arm64、Windows x64),缓存在 ~/.cloakbrowser/。
最小可运行示例
from cloakbrowser import launch
browser = launch(headless=False)
page = browser.new_page()
page.goto("https://bot.sannysoft.com")
page.screenshot(path="stealth_test.png")
browser.close()
打开截图你会看到 navigator.webdriver 是 false、plugins 有 5 个、chrome 对象存在、UA 是正常 Chrome——全部绿灯。
关键参数
from cloakbrowser import launch
browser = launch(
proxy="socks5://user:pass@proxy:1080", # SOCKS5 比 HTTP 代理更稳
geoip=True, # 从代理 IP 推断时区和语言
headless=False, # 有头模式(配合 xvfb 在服务器跑)
humanize=True, # 人类化鼠标/键盘/滚动
args=["--fingerprint=42069"], # 固定种子,保持身份一致
)
对于难搞的站点,官方推荐的「黄金组合」:
proxy (住宅) + geoip=True + headless=False + humanize=True
humanize:行为级反检测
单独指纹不够,现代反机器人系统还看鼠标轨迹、键盘间隔、滚动模式。humanize=True 会把所有 Playwright 调用替换为人类化版本:
| 动作 | 默认 | humanize=True |
|---|---|---|
| 鼠标移动 | 瞬移 | 贝塞尔曲线 + 缓动 + 轻微过冲 |
| 点击 | 立即 | 真实落点 + 按压时长 |
| 键盘 | 瞬间填充 | 逐字符计时 + 思考停顿 + 偶尔打错再修正 |
| 滚动 | 跳跃 | 加速→匀速→减速微步进 |
browser = launch(humanize=True, human_preset="careful") # careful 更慢、更像真人
可以进一步自定义:
browser = launch(humanize=True, human_config={
"mistype_chance": 0.05, # 5% 打错修正率
"typing_delay": 100, # 每字符 100ms
"idle_between_actions": True, # 点击间微小鼠标游移
"idle_between_duration": [0.3, 0.8],
})
持久化 Profile
匿名/隐身模式本身就是检测信号。用 launch_persistent_context() 保留 cookies、localStorage:
from cloakbrowser import launch_persistent_context
ctx = launch_persistent_context("./my-profile", headless=False)
page = ctx.new_page()
page.goto("https://example.com")
# 登录、浏览,cookies 会保留在 ./my-profile/
ctx.close()
# 下次运行自动恢复
ctx = launch_persistent_context("./my-profile")
Docker 与 CDP 服务模式
CloakBrowser 提供官方镜像 cloakhq/cloakbrowser,里面预装了反检测需要的字体包(fonts-noto-color-emoji 等)。
快速验证:
docker run --rm cloakhq/cloakbrowser cloaktest
关键模式:cloakserve——把 CloakBrowser 跑成一个 CDP 服务:
docker run -d --name cloak -p 9222:9222 cloakhq/cloakbrowser cloakserve
然后从任何机器用 Playwright 连过去:
from playwright.sync_api import sync_playwright
pw = sync_playwright().start()
browser = pw.chromium.connect_over_cdp("http://localhost:9222")
page = browser.new_page()
page.goto("https://example.com")
browser.close()
这个模式才是把 CloakBrowser 接入到浏览器池系统(比如 BrowserStation)的基础。
每连接不同指纹
cloakserve 支持通过 URL 参数给每个连接分配独立的指纹种子和身份:
b1 = pw.chromium.connect_over_cdp("http://localhost:9222?fingerprint=11111")
b2 = pw.chromium.connect_over_cdp("http://localhost:9222?fingerprint=22222")
# 完整身份参数
b3 = pw.chromium.connect_over_cdp(
"http://localhost:9222?fingerprint=33333"
"&timezone=Asia/Tokyo&locale=ja-JP&platform=macos"
"&hardware-concurrency=4&device-memory=8"
)
相同 seed 复用同一个 Chrome 进程,不同 seed 会起新进程——单容器可以同时承载多个身份。
四、竞品对比
这个赛道大致分三类:代码库级、独立浏览器(开源)、商业指纹浏览器 SaaS。
对比总表
| 项 | Playwright 原生 | playwright-stealth | undetected-chromedriver | Camoufox | CloakBrowser | Multilogin/AdsPower | 青果/比特 |
|---|---|---|---|---|---|---|---|
| 补丁层级 | 无 | JS 注入 | 启动参数 | C++(Firefox) | C++(Chromium) | C++(定制 Chromium) | C++(定制 Chromium) |
| reCAPTCHA v3 | 0.1 | 0.3-0.5 | 0.3-0.7 | 0.7-0.9 | 0.9 | 0.7-0.9 | 0.7-0.9 |
| Cloudflare Turnstile | Fail | 偶尔过 | 偶尔过 | Pass | Pass | Pass | Pass |
| 抗 Chrome 升级 | N/A | 经常失效 | 经常失效 | 是 | 是 | 是 | 是 |
| 维护活跃度 | 官方 | 停滞 | 停滞 | 不稳定 | 活跃 | 商业公司 | 商业公司 |
| 引擎 | Chromium | Chromium | Chrome | Firefox | Chromium | Chromium | Chromium |
| Playwright 原生支持 | ✅ | ✅ | ❌(Selenium) | ❌ | ✅ | 需 CDP 桥接 | 需 CDP 桥接 |
| License | Apache 2.0 | MIT | MIT | MPL | MIT + 二进制自由用 | 商业闭源 | 商业闭源 |
| 价格 | 免费 | 免费 | 免费 | 免费 | 免费 | $99+/月 | ¥200+/月 |
| 自托管 | 是 | 是 | 是 | 是 | 是 | 否 | 否 |
| 团队协作 Profile 管理 | 无 | 无 | 无 | 无 | Manager 模块(开源) | ✅ | ✅ |
具体差异
CloakBrowser vs Camoufox
两个最接近的竞品。我仓库里还有一篇 Camofox:给 AI Agent 用的反指纹浏览器 专门讲 Camoufox。
- 引擎:Camoufox 改 Firefox,CloakBrowser 改 Chromium
- Playwright 生态:CloakBrowser 更原生(Playwright 本身对 Chromium 支持更深)
- 指纹可信度:Chrome 市占率远高于 Firefox,伪装成 Chrome 不容易被 IP-UA 聚类
- TLS 指纹:CloakBrowser 使用 Chrome 的 BoringSSL,TLS 指纹完美匹配
- 稳定性:2026 年初 Camoufox 停更过一段时间,CloakBrowser 当前迭代更活跃
- AI Agent 工具生态:Browser-use、Crawl4AI、Stagehand 都原生支持 Playwright + Chromium
什么时候选 Camoufox:目标站点对 Firefox 不敏感,或者你希望避开 Chromium 独有的检测路径。
CloakBrowser vs playwright-stealth / undetected-chromedriver
前者是二进制方案,后者是配置方案——前者维护成本高(要编译),但效果稳定;后者安装简单,但每次 Chrome 升级都可能断裂,且 JS 注入本身是检测信号。
什么时候还用 playwright-stealth:做一次性的简单抓取,目标站点只有基础检测。
CloakBrowser vs 商业指纹浏览器(Multilogin、AdsPower、BitBrowser)
商业方案的核心价值是多账号管理:图形化 profile 仓库、团队共享、代理绑定、Cookie 同步等。纯做抓取、Agent 自动化用不上这些,CloakBrowser 就够了。
如果你需要账号管理功能,CloakBrowser 也有配套的 Manager 模块 开源版,docker 一行启动:
docker run -p 8080:8080 -v cloakprofiles:/data cloakhq/cloakbrowser-manager
访问 http://localhost:8080 就能可视化管理 profile,是 Multilogin/GoLogin 的免费替代。
选型决策树
是只想跑简单抓取吗?
├─ 是 → playwright-stealth(够用)
└─ 否
└─ 目标站点有 CF Turnstile / FingerprintJS / reCAPTCHA v3 吗?
├─ 没有 → playwright-stealth 或 undetected-chromedriver
└─ 有
├─ 需要多账号 GUI 管理吗?
│ ├─ 是 + 预算充足 → Multilogin/AdsPower
│ └─ 是 + 想自托管 → CloakBrowser + Manager 模块
└─ 否,只做自动化
├─ 目标站点对 Firefox 宽容 → Camoufox
└─ 目标站点偏爱 Chrome 或用 Playwright 生态 → **CloakBrowser**
五、集成到 BrowserStation
之前写过 BrowserStation 浏览器池搭建,默认用的是 zenika/alpine-chrome:100 作为每个 Worker Pod 的 Chrome 容器。这个镜像是普通 Chromium,对上反检测场景就歇菜了。把它替换成 CloakBrowser 后,整个浏览器池立刻变成反检测池。
集成思路
BrowserStation 的架构本来就是 CDP 协议解耦——Head 节点通过 ws://worker:9222/devtools/browser/xxx 代理 WebSocket,只要 Worker 暴露的是标准 CDP 9222,Head 根本不关心底层是哪种 Chrome。
所以集成只需要两步:
- 把
chrome容器从zenika/alpine-chrome:100换成cloakhq/cloakbrowser - 启动命令从 Chromium 的
--remote-debugging-port=9222换成cloakserve
修改 RayService YAML
基于之前文章里的 RayService 配置,修改 workerGroupSpecs.template.spec.containers 里的 chrome 容器:
workerGroupSpecs:
- groupName: browser-workers
replicas: 9
rayStartParams: {}
template:
spec:
containers:
- name: ray-worker
image: browserstation:v1.0
imagePullPolicy: Never
resources:
requests:
cpu: "100m"
memory: "256Mi"
# === 这里改动 ===
- name: chrome
image: cloakhq/cloakbrowser:latest # 替换镜像
imagePullPolicy: IfNotPresent
securityContext:
runAsUser: 0
runAsNonRoot: false
command: ["cloakserve"] # 用 cloakserve 代替默认 chromium
args:
- "--host=0.0.0.0"
- "--port=9222"
env:
- name: CLOAKBROWSER_AUTO_UPDATE
value: "false" # 离线环境关闭自动更新
ports:
- containerPort: 9222
name: devtools
resources:
requests:
cpu: "1500m" # Cloak 比 alpine-chrome 多吃约 50% CPU
memory: "1Gi" # 含字体、patch 后的 runtime
limits:
cpu: "2000m"
memory: "1536Mi"
volumeMounts:
- name: cloak-cache
mountPath: /root/.cloakbrowser
volumes:
- name: cloak-cache
emptyDir: {}
关键差异:
| 项 | 原 alpine-chrome | CloakBrowser |
|---|---|---|
| 镜像大小 | ~180MB | ~450MB(含字体和 patch 后的 Chromium) |
| CPU 请求 | 900m | 1500m |
| 内存请求 | 768Mi | 1Gi |
| 启动命令 | chromium --remote-debugging-port=... |
cloakserve --host=... --port=... |
| 二进制存储 | 镜像内 | 首次下载 + 挂载缓存目录 |
离线部署的做法
原文章里用 docker save 导出再 k3s ctr images import 离线导入。CloakBrowser 可以同样操作:
# 拉取 + 预热二进制(避免首次启动下载)
docker run --rm cloakhq/cloakbrowser python -m cloakbrowser install
docker commit $(docker ps -lq) cloakbrowser:preloaded
# 导出
docker save cloakbrowser:preloaded | gzip > cloakbrowser-preloaded.tar.gz
# 分发到所有 Agent 并导入
scp cloakbrowser-preloaded.tar.gz agent01:/opt/k3s-offline/
ssh agent01 "gunzip -c /opt/k3s-offline/cloakbrowser-preloaded.tar.gz | k3s ctr images import -"
然后把 YAML 里的 image: cloakhq/cloakbrowser:latest 改成 image: cloakbrowser:preloaded,同时把 imagePullPolicy 改回 Never。
FastAPI 调度层改动
BrowserStation 的 Head 节点负责分配浏览器实例。为了利用 CloakBrowser 的「每连接独立指纹」能力,可以扩展 POST /browsers 接口:
# app/main.py 里的分配接口
@app.post("/browsers")
async def create_browser(req: CreateBrowserRequest):
worker = pick_least_loaded_worker()
# 原来的 WS URL
# ws_url = f"ws://{worker.ip}:9222/devtools/browser/{session_id}"
# 改成:把用户指定的 fingerprint 参数透传给 cloakserve
params = urlencode({
"fingerprint": req.fingerprint_seed or random_seed(),
"timezone": req.timezone or "",
"locale": req.locale or "",
"proxy": req.proxy or "",
"geoip": "true" if req.geoip else "",
})
ws_url = f"ws://{worker.ip}:9222?{params}"
return {
"id": session_id,
"ws_url": ws_url,
"worker": worker.name,
"fingerprint": params,
}
对应的请求体:
class CreateBrowserRequest(BaseModel):
fingerprint_seed: Optional[int] = None
timezone: Optional[str] = None
locale: Optional[str] = None
proxy: Optional[str] = None
geoip: bool = False
humanize: bool = True
这样客户端可以明确指定身份:
import httpx
r = httpx.post("http://10.0.0.10:30050/browsers", json={
"fingerprint_seed": 42069,
"timezone": "Asia/Shanghai",
"locale": "zh-CN",
"proxy": "socks5://user:pass@sg-proxy:1080",
"geoip": True,
})
ws_url = r.json()["ws_url"]
客户端对接
客户端代码几乎不用变(Playwright CDP 连接就能拿到反检测效果):
from playwright.async_api import async_playwright
import httpx, asyncio
API = "http://10.0.0.10:30050"
async def main():
r = httpx.post(f"{API}/browsers", json={
"fingerprint_seed": 12345,
"timezone": "America/New_York",
"locale": "en-US",
"humanize": True,
})
info = r.json()
async with async_playwright() as p:
browser = await p.chromium.connect_over_cdp(info["ws_url"])
page = browser.contexts[0].pages[0]
await page.goto("https://bot.sannysoft.com")
await page.screenshot(path="cloak-via-browserstation.png")
await browser.close()
httpx.delete(f"{API}/browsers/{info['id']}")
asyncio.run(main())
注意:humanize 是 wrapper 层特性,跨 CDP 连接时默认丢失。要在客户端恢复,需要手动 patch:
// Node 客户端
import { patchBrowser, resolveConfig } from 'cloakbrowser/human';
const browser = await playwright.chromium.connectOverCDP(wsUrl);
patchBrowser(browser, resolveConfig('default'));
Python 目前还需要在客户端自己实现人类化(或者把 humanize 逻辑搬到 BrowserStation 的 FastAPI 层做一次封装)。
资源规划调整
原配置是每个 Worker Pod 跑 1 个 Chrome,基于新资源需求重新算账:
| 资源 | 原配置(alpine-chrome) | CloakBrowser |
|---|---|---|
| 单 Worker CPU | 1 core (100m + 900m) | 1.6 core (100m + 1500m) |
| 单 Worker 内存 | 1Gi (256Mi + 768Mi) | 1.25Gi (256Mi + 1Gi) |
| 镜像大小 | ~200MB | ~450MB |
| 每台 8C16G Agent 能跑几个 Worker | 7-8 | 4-5 |
10 台 Agent,单 Worker 配 CloakBrowser 的话,集群容量大概从 72 个并发浏览器降到 45 个并发浏览器。如果并发需求高,要么扩节点,要么把 Agent 规格提到 16C32G。
另一种策略是用 cloakserve 的多连接单进程特性:同一个容器里跑多个浏览器会话(不同 fingerprint seed 走不同 Chrome 进程,但共享同一个 cloakserve 服务),可以把 Worker Pod 改成一对多:
- name: chrome
image: cloakhq/cloakbrowser:latest
command: ["cloakserve"]
args:
- "--host=0.0.0.0"
- "--port=9222"
- "--max-browsers=5" # 假设支持,依具体版本
resources:
requests:
cpu: "4000m" # 预留足够 CPU
memory: "4Gi"
然后在 Ray Actor 层做二次池化,一个容器对外呈现 5 个 "virtual browser",这样整体密度接近原来。
一条完整的验证流程
部署好之后,跑一遍端到端:
# 1. 确认 Pod 跑起来
kubectl get pods -n ray-system
# browser-cluster-worker-xxx 2/2 Running ← 注意 2/2 sidecar
# 2. 确认 cloakserve 就绪
kubectl exec -n ray-system browser-cluster-worker-xxx -c chrome -- \
curl -s http://localhost:9222/json/version | jq
# {
# "Browser": "Chrome/146.0.7680.177", ← 注意不是 HeadlessChrome
# "Protocol-Version": "1.3",
# "User-Agent": "Mozilla/5.0 ... Chrome/146.0.0.0 ..."
# }
# 3. 从 Head 申请一个实例
curl -X POST http://10.0.0.10:30050/browsers \
-H "Content-Type: application/json" \
-d '{"fingerprint_seed": 42069, "humanize": true}'
# 4. 跑一次 bot.sannysoft 测试
python cloak-via-browserstation-test.py
通过 bot.sannysoft.com 看到全部 webdriver / plugins / chrome / permission 绿灯,就成了。
六、几个实战注意点
-
字体是关键:Kasada/Akamai 会渲染 emoji 到 canvas 然后算 hash。CloakBrowser 官方镜像已经装了 emoji 字体,但如果你自己基于
python:slim构建,要手动apt install fonts-noto-color-emoji fonts-freefont-ttf。 -
page.wait_for_timeout()会降分:这个 Playwright API 会发 CDP 协议包,reCAPTCHA 能检测到。换成time.sleep()或await asyncio.sleep()。 -
住宅代理比浏览器指纹更重要:数据中心 IP 无论指纹多完美都会被 IP 信誉系统拦。预算够就买住宅代理,预算紧就买共享住宅池(如 Bright Data、NetNut 的 pay-as-you-go 套餐)。
-
固定 seed vs 随机 seed:
- 同一站点反复访问 → 固定 seed(像回头客)
- 多账号独立隔离 → 每账号一个固定 seed
- 一次性大规模抓取不同域名 → 随机 seed
-
Playwright 优于 Puppeteer:官方明确建议在处理 reCAPTCHA Enterprise 时用 Playwright,Puppeteer 的 CDP 协议会泄露更多自动化信号。
-
Binary License 限制商用行为:wrapper 代码 MIT,但编译后的 Chromium 二进制是「自由使用但禁止重分发」。做内部自动化没问题,但不能打包进自己的商业产品分发。
七、什么时候不该用 CloakBrowser
为了平衡,列几个不该选它的场景:
- 只做基础爬虫,目标站点没有任何反机器人措施——用原生 Playwright 就行,别增加复杂度
- 对二进制可审计性要求极高(金融/政府场景)——编译二进制来自第三方,源码虽开放但编译链路不透明
- 需要 Firefox 引擎特性(比如某些 extension 只有 Firefox 版本)——看 Camoufox
- 要商业多账号管理平台(有客户 onboarding、审计日志、合规)——付钱买 Multilogin
- 目标站点已经识别了 CloakBrowser 本身(极少见,但不排除)——需要自己编译补丁改掉指纹签名
总结
CloakBrowser 在反检测赛道做对了两件事:把补丁打在最难被检测的 C++ 层,以及完全兼容 Playwright 生态。对比之前要么用破碎的 JS 注入、要么花钱买商业指纹浏览器的局面,它给了一个开源、免费、能自托管、且足够生产用的选项。
接入到 BrowserStation 这类浏览器池系统里,只需要替换 chrome sidecar 的镜像和启动命令,上层调度逻辑一点不用改——这是 CDP 协议解耦架构的最大好处。做出来之后,你就有了一个 10 节点、45 并发、分布式、反检测的浏览器池,可以撑 AI Agent 批量跑真实网页任务,也可以给爬虫团队当共享基础设施。
参考资源:
- CloakBrowser 仓库:https://github.com/CloakHQ/CloakBrowser
- Manager 模块:https://github.com/CloakHQ/CloakBrowser-Manager
- 二进制构建:https://github.com/CloakHQ/chromium-stealth-builds
- 官方网站:https://cloakbrowser.dev
- BrowserStation:https://github.com/ReinforceNow/browserstation
- 本站相关:BrowserStation 浏览器池搭建、Camofox:给 AI Agent 用的反指纹浏览器、指纹浏览器:原理、对抗与实践